from datetime import datetime

from sqlalchemy import *
from sqlalchemy.ext.activemapper import ActiveMapper, column, \
                                    one_to_many, one_to_one, many_to_many
from sqlalchemy.ext.assignmapper import assign_mapper

from turbogears import identity 
from turbogears.database import metadata, session

from docutils.core import publish_parts

post_table = Table("posts", metadata,
    Column("id", Integer, primary_key=True),
    Column("title", Unicode(50)),
    Column("content", Unicode),
    Column("post_date", DateTime, default=datetime.now),
    Column("is_published", Boolean, default=False),
)
class Post(object):
    
    def _get_html_content(self):
        return publish_parts(self.content,
                writer_name="html")["html_body"]
    html_content = property(_get_html_content)



assign_mapper(session.context, Post, post_table)


class Visit(ActiveMapper):
    class mapping:
        __table__ = "visit"
        visit_key = column(String(40), primary_key=True)
        created = column(DateTime, nullable=False, default=datetime.now)
        expiry = column(DateTime)

    def lookup_visit(cls, visit_key):
        return Visit.get(visit_key)
    lookup_visit = classmethod(lookup_visit)

# tables for SQLAlchemy identity
user_group = Table("user_group", metadata, 
                      Column("user_id", Integer,
                              ForeignKey("tg_user.user_id"),
                              primary_key=True),
                      Column("group_id", Integer,
                              ForeignKey("tg_group.group_id"),
                              primary_key=True))

group_permission = Table("group_permission", metadata,
                            Column("group_id", Integer,
                                    ForeignKey("tg_group.group_id"),
                                    primary_key=True),
                            Column("permission_id", Integer,
                                ForeignKey("permission.permission_id"),
                                    primary_key=True))


class VisitIdentity(ActiveMapper):
    class mapping:
        __table__ = "visit_identity"
        visit_key = column(String(40), # foreign_key="visit.visit_key",
                          primary_key=True)
        user_id = column(Integer, foreign_key="tg_user.user_id", index=True)


class Group(ActiveMapper):
    """
    An ultra-simple group definition.
    """
    class mapping:
        __table__ = "tg_group"
        group_id = column(Integer, primary_key=True)
        group_name = column(Unicode(16), unique=True)
        display_name = column(Unicode(255))
        created = column(DateTime, default=datetime.now)

        users = many_to_many("User", user_group, backref="groups")
        permissions = many_to_many("Permission", group_permission,
                                   backref="groups")


class User(ActiveMapper):
    """
    Reasonably basic User definition. Probably would want additional attributes.
    """
    class mapping:
        __table__ = "tg_user"
        user_id = column(Integer, primary_key=True)
        user_name = column(Unicode(16), unique=True)
        email_address = column(Unicode(255), unique=True)
        display_name = column(Unicode(255))
        password = column(Unicode(40))
        created = column(DateTime, default=datetime.now)

        groups = many_to_many("Group", user_group, backref="users")

    def permissions(self):
        perms = set()
        for g in self.groups:
            perms = perms | set(g.permissions)
        return perms
    permissions = property(permissions)


class Permission(ActiveMapper):
    class mapping:
        __table__ = "permission"
        permission_id = column(Integer, primary_key=True)
        permission_name = column(Unicode(16), unique=True)
        description = column(Unicode(255))

        groups = many_to_many("Group", group_permission,
                              backref="permissions")
